package queue

import (
	"errors"
	"sync"
)

var (
	Queuefifo *QueueFIFO
)

// QueueFIFO 先入先出队列
type QueueFIFO struct {
	len    uint32
	maxLen uint32
	mu     sync.Mutex
	first  *QueueItem
	last   *QueueItem
}

type QueueItem struct {
	data interface{}
	prev *QueueItem
	next *QueueItem
}

func New(len uint32) *QueueFIFO {
	return &QueueFIFO{
		maxLen: len,
	}
}

func (q *QueueFIFO) Len() uint32 { return q.len }

func (q *QueueFIFO) Push(data interface{}) error {
	q.mu.Lock()
	defer q.mu.Unlock()
	if q.len == q.maxLen {
		return errors.New("queue has reached the maximum length")
	}
	item := &QueueItem{
		data: data,
		prev: nil,
		next: nil,
	}
	if q.len == 0 {
		q.first = item
		q.last = item
	} else {
		q.last.next = item
		item.prev = q.last
		q.last = item
	}
	q.len++
	return nil
}

func (q *QueueFIFO) Pop() interface{} {
	q.mu.Lock()
	defer q.mu.Unlock()
	if q.first == nil {
		return nil
	}
	data := q.first.data
	q.first = q.first.next
	if q.first != nil {
		q.first.prev = nil
	}
	q.len--
	return data
}
